/**
 * visKMedoids.cpp
 * Linux(ubuntu8.04),g++4.3.2
 * Copyright,2/3/2009,LU_CGCAD_THSS_THU_BJ
 * Author: Xinlai,Lu
 */

#include "visKMedoids.h"

namespace visualization
{
void visKMedoids::relocate(unsigned int itrtNum)
{
	/**
	 * For each streamline, compute and determine the class it belongs to acoording to 
	 * the distance used.
	 */
	for(unsigned int numLn = 0; numLn < getStreamlinesNumber(); numLn++)
	{
		if(0 == getStreamlineSize(numLn))continue;
		double tmp = DBL_MAX;
		for(unsigned int numCls = 0; numCls < m_NumClusters; numCls++)
		{
			/**Compute the distance between a streamline and a cluster center, and switch the 
			 * class to which 'numLn' belongs to numCls if they are more similar.
			 *
			 * Note that the default distance is Euclidean distance.
			 */
			double deSim = computeDeSimilarity(numLn, getClusterCenters(itrtNum, numCls));
			if( tmp > deSim )
			{
				tmp = deSim;
				m_ObjIsClassVec[numLn] = numCls;
			}
		}//for
	}//for
}

_STATUS visKMedoids::updateClusterCenters(unsigned int itrtNum)
{
  /* Update the centers, calculate the total error, and then determine the clustering status.
	 * 
	 */
	/**
	 * @Modification 4 : the m_ClassHaveObjVec is slightly modified.
	 */
	for(unsigned int obj = 0; obj < getStreamlinesNumber(); obj++)
	{
		unsigned int classId = m_ObjIsClassVec[obj];
		/**
		 * @Modification 4.
		 */
		//m_ClassHaveObjVec[classId + itrtNum*m_NumClusters].push_back(obj);
		setClusterMember(itrtNum, classId, obj);
	}
	reshapeCluster2One(DIS_WEIGHTED, itrtNum);
	for(unsigned int i = 0; i < m_NumClusters; i++)
	{
		double tmp = DBL_MAX;
		vector<Point> tmpCnt = getClusterCenters(itrtNum+1, i);
		unsigned int tmpMem, mem;
		for(unsigned int j = 0; j < getClusterMembers(itrtNum, i).size(); j++)
		{
			tmpMem = getClusterMember(itrtNum, i, j);
			double deSim = computeDeSimilarity(tmpMem, tmpCnt);
			if( tmp > deSim )	
			{	
				tmp = deSim; 
				mem = tmpMem;
			}
		}
		getClusterCenters(itrtNum+1, i).clear();
		for(unsigned int m = 0; m < getStreamlineSize(mem); m++)
		{
			Point tmp = getPointOnStreamline(mem, m);
			setClusterCenter(itrtNum+1, i, tmp);
		}
	}
	// If the cluster results have no changes.
	double error = totalError();
	if( abs(error - m_Error) < 1e-6 )
	{
		return _CLUSTERING_END;
	}
	else
	{
		m_Error = error;
		return _CLUSTERING_CONTINUE;
	}
}
}

